<?php
// +----------------------------------------------------------------------
// | Description: base controller no auth
// +----------------------------------------------------------------------
// | Author: orchief
// +----------------------------------------------------------------------

namespace app\client\controller;

use app\client\model\Member;
use app\client\model\SkuItem;
use app\common\controller\Common;
use EasyWeChat\Factory;
use SmsCode\SmsModel;
use think\image\Exception;
use think\Request;
use \Firebase\JWT\JWT;
use think\Db;
use EasyWeChat\Kernel\Messages\Image;
use EasyWeChat\Kernel\Messages\NewsItem;
/**
 * Class Base
 * @package app\admin\controller
 */
class Base extends Common
{
    public function test()
    {
    }

    /**
     * 微信服务器推送
     *
     * @return void
     */
    public function wechatPush()
    {
        $config = [
            'app_id' => 'wx5876e5d51f69fbd9',
            // 'secret' => '9be0f0536ec0561d3731197729aa341e',
            'secret' => '5894359d5e661151a54dafef351144ab',
            'token'   => 'ceshi',          // Token

            // 指定 API 调用返回结果的类型：array(default)/collection/object/raw/自定义类名
            'response_type' => 'array',

            'log' => [
                'level' => 'debug',
                'file' => './wechat2.log',
            ],
        ];

        $app = Factory::officialAccount($config);

        $app->server->push(function ($message) {

        	//return '欢迎关注婴盾母婴商城';
           	//获取联系电话
            if($message['EventKey'] == 'server-phone'){
                
                return '0532-85051035';
            }
            //获取微信客服
            if($message['EventKey'] == 'server-people'){
                $image = new Image('rBisZaemsxAaW_7e27oPMuvogbEKdNRtWPm3QFnCJRE');
                return $image;
            }
            //关注事件 获取代金券
            if($message['Event'] == 'subscribe'){
                /*$items = [
                    new NewsItem([
                        'title'       => '代金券二维码',
                        'description' => '欢迎关注婴盾母婴商城,请领取代金券',
                        //'url'         => ,
                        'image'       => 'https://mmbiz.qpic.cn/mmbiz_png/L0FR3nc4sKnaNWIyRgB0So2FoU39T2R0hxmQ0ycE7JPpctaOSPT3amkkMKiajYSG8krvibib4Aicbqv687tZSJRnKA/0?wx_fmt=png',
                    ])
                ];*/
                $image = new Image('rBisZaemsxAaW_7e27oPMrz6C-GxKFy_RINgZ9wMzHY');
                return $image;
            }
            //自动回复
            if(isset($message['FromUserName'])){
                $data['OpenId'] = $message['FromUserName'];
                $data['ReferUserId'] = $message['EventKey'];

                Db::table('shop_members_temp')->insert($data);
                return '欢迎关注婴盾母婴商城';
            }
            //return '欢迎关注婴盾母婴商城,领取卡券';
        });

        $response = $app->server->serve();

        $response->send();
    }

    /**
     * sign up
     *
     * @return void
     */
    public function signUp()
    {
        $validate = validate('base');
        $this->abort($validate->scene('signUp')->check($this->param), $validate->getError());

        // 检查推荐人是否存在
        $Member = new Member();
        $res = $Member->get($this->param['ReferUserId']);
        $this->abort($res, ['msg' =>  '推荐人错误,请重新扫描推荐二维码!']);
        $this->param['ReferUserName'] = $res['UserName'];
        $this->param['ReferCellPhone'] =  $res['CellPhone'];
        $this->checkCode();
        $Member = new Member();
        $salt = uniqid();
        $this->param['PasswordSalt'] = $salt;
        $this->param['Password'] = user_md5($this->param['Password'], $salt);
        $this->checkRes($Member->createData($this->param), '注册成功!', $Member->getError());
    }

    /**
     * login
     *
     * @return void
     */
    public function login()
    {
        $ErrorMsg = '登录失败!';
        $key = config('jwt.key'); // 签名秘钥
        $expire = config('jwt.expire'); // 俩小时失效
        $refresh = $expire + 60; // 令牌失效60秒之内可以重新获取

        $Member = new Member();
        $userInfo = $Member->where(['CellPhone' => $this->param['CellPhone']])->find();
        if(!$userInfo){
            $userInfo = $Member->where(['UserName' => $this->param['CellPhone']])->find();
        }
        // 如果是微信端 则 存储用户openid
        if ($this->param['OpenId']) {
            try {
                $Member->where(['Id' => $userInfo['Id']])->update(['OpenId' => $this->param['OpenId']]);

                // 检查该用户是否有推荐人 如果没有 则将临时表中数据取出 给该用户当推荐人
                if($userInfo['ReferUserId'] == 0 and $userInfo['Id'] != 1) {  // id为 1 不需要推荐人
                    $tempData = Db::table('shop_members_temp') ->  where(['OpenId' => $this->param['OpenId']]) -> find();
                    if(!$tempData){
                        $ErrorMsg = '请扫码绑定推荐人!';
                        $this -> abort(false, '121');
                    }else{
                        if($userInfo['Id'] == $tempData['ReferUserId']){
                            $ErrorMsg = '请扫码绑定推荐人!';
                            $this -> abort(false, '121');
                        }
                        $referInfo = $Member -> where(['Id' => $tempData['ReferUserId']]) -> find();
                        $Member ->where(['CellPhone' => $userInfo['CellPhone']]) -> update(['ReferUserId' => $tempData['ReferUserId'], 'ReferUserName' => $referInfo['UserName'], 'ReferCellPhone' => $referInfo['CellPhone']]);
                    }
                }

            } catch (\Exception $e) {
                $this->abort(false, $ErrorMsg);
            }
        }

        $this->abort($userInfo, '手机号不存在!');
        $this->abort($userInfo['Enabled'], '账户被冻结!');
        $data['UserId'] = $userInfo['Id'];
        $data['expireDate'] = time() + $expire; // 规定令牌失效时间
        $data['refreshDate'] = time() + $refresh; // 规定令牌失效之后可重新获取的时间

        $jwt = JWT::encode($data, $key);

        try {
            session('MemberInfo', $userInfo);
        } catch (\Exception $e) {
            $this->abort(false, $e->getMessage());
        }
        $this->checkRes($userInfo['Password'] == \user_md5($this->param['Password'], $userInfo['PasswordSalt']), $jwt, '用户名或密码错误');
    }

    /**
     * get wechat openid
     *
     * @return void
     */
    public function wechatLogin()
    {
        // p(1);
        $config = [
            'app_id' => config('wechat.app_id'),
            'secret' => config('wechat.secret'),

            // 指定 API 调用返回结果的类型：array(default)/collection/object/raw/自定义类名
            'response_type' => 'array',

            'oauth' => [
                'scopes' => ['snsapi_base'],
                'callback' => '/base/oauth_callback',
            ],

            'log' => [
                'level' => 'debug',
                'file' => __DIR__ . '/wechat.log',
            ],
        ];

        $app = Factory::officialAccount($config);
        $oauth = $app->oauth;

        $Member = new Member();
        $MemberInfo = $Member->get($this->param['UserId']);
        $oauth->redirect()->send();
    }

    /**
     * 授权回调
     *
     * @return void
     */
    public function oauth_callback()
    {
        // p(1);
        $config = [
            'app_id' => config('wechat.app_id'),
            'secret' => config('wechat.secret'),

            // 指定 API 调用返回结果的类型：array(default)/collection/object/raw/自定义类名
            'response_type' => 'array',

            'log' => [
                'level' => 'debug',
                'file' => __DIR__ . '/wechat.log',
            ],
        ];

        $app = Factory::officialAccount($config);
        $oauth = $app->oauth;

        // 获取 OAuth 授权结果用户信息
        $user = $oauth->user();
        header('Location: /wx/login?OpenId=' . $user['id']);
    }

    public function refreshToken()
    {
        $headers = Request::instance()->header();
        $this->abort($headers['authorization'], '缺少必要参数');
        $key = config('jwt.key'); // 签名秘钥

        $headers['authorization'] = $headers['authorization'];
        try {
            $decoded = JWT::decode($headers['authorization'], $key, array('HS256'));
        } catch (\Exception $e) {
            $this->abort(false, '鉴权失败');
        }

        $Member = new Member();

        $resArr = $this->object_to_array($decoded);

        $this->abort($resArr['refreshDate'] > time(), '令牌已过重新获取有效期, 请重新登录');

        $expire = config('jwt.expire'); // 俩小时失效
        $refresh = $expire + 60; // 令牌失效60秒之内可以重新获取

        $resArr['expireDate'] = time() + $expire;
        $resArr['refreshDate'] = time() + $refresh;
        try {
            $jwt = JWT::encode($resArr, $key);
        } catch (\Exception $e) {
            $this->abort(false, '获取失败');
        }

        $this->jsonData($jwt);
    }

    /**
     * reset pass by phoneNum
     *
     * @return void
     */
    public function resetPassByPhone()
    {
        $this->checkCode();
        $this->abort($this->param['NewPass'], '新密码不能为空!');
        $param['Password'] = $this->param['NewPass'];
        $Member = new Member();
        $MemberInfo = $Member->where(['CellPhone' => $this->param['CellPhone']])->find();
        $this->abort($MemberInfo, $Member->getError());
        $salt = $MemberInfo['PasswordSalt'];
        $param['Password'] = user_md5($param['Password'], $salt);
        // p($param);
        try {
            $res = $Member->where(['CellPhone' => $this->param['CellPhone']])->update($param);
        } catch (\Exception $e) {
            $this->checkRes($res, '重置成功!', $e->getMessage());
        }
        $this->jsonData('重置成功!');
    }

    /**
     * 注销
     *
     * @return void
     */
    public function logout()
    {
        try {
            session('MemberInfo', null);
        } catch (\Exception $e) {
            $this->abort(false, $e->getMessage());
        }
        $this->jsonData('退出成功!');
    }

    /**
     * Getting SMS authentication code
     */
    public function SmsCode()
    {
        $queryTimes = 60; // Frequency default 60s

        $time = time() - session('SmsExpireDate');

        $this->abort($time >= $queryTimes, '您已获取验证码, 请' . ($queryTimes - $time) . '秒后重试');

        $SmsModel = new SmsModel();

        $this->abort(!empty($this->param['CellPhone']), '手机号不能为空');

        $res = $SmsModel->getCode($this->param['CellPhone']);

        $this->abort($res, $SmsModel->getError());

        // Failure time
        session('SmsExpireDate', time());

        $this->checkRes($res, '获取成功', $SmsModel->getError());
    }

    /**
     * by skuitems get sku
     *
     * @return void
     */
    public function sku()
    {
        $model = new SkuItem();
        $data = $model->getSku($this->param);
        $this->jsonData($data, $model->getError());
    }

    /**
     * array to object
     *
     * @param object $obj Object
     * @return array
     */
    public function object_to_array($obj)
    {
        $obj = (array) $obj;
        foreach ($obj as $k => $v) {
            if (gettype($v) == 'resource') {
                return;
            }
            if (gettype($v) == 'object' || gettype($v) == 'array') {
                $obj[$k] = (array) object_to_array($v);
            }
        }

        return $obj;
    }

// ------------------------------------------------------------------
    // private
    // ------------------------------------------------------------------
    /**
     * check phone num if exist
     *
     * @return void
     */
    private function checkPhone($cellPhone)
    {
        $Member = new Member();
        $this->abort(!($Member->where(['CellPhone' => $cellPhone])->count()), '账户已存在');
    }

    /**
     * check sms code
     */
    protected function checkCode()
    {
        $this->abort(!empty($this->param['code']), '请输入验证码');
        $MaxTimes = 60 * 5;
        // Verification code aging
        $time = time() - session('SmsExpireDate');
        $this->abort($time < $MaxTimes, '您的验证码已失效, 请重新获取');
        $code = session('code');
        $phone = session('CellPhone');
        $this->abort($code == $this->param['code'] and ($phone == $this->param['CellPhone']), '验证码错误');
    }

    /**
     * get unique username
     *
     * @return void
     */
    public function getUniqueUserName()
    {
        $chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $username = "";
        for ($i = 0; $i < 6; $i++) {
            $username .= $chars[mt_rand(0, strlen($chars))];
        }
        return strtoupper(base_convert(time() - 1420070400, 10, 36)) . $username;
    }

   /**
     * 请求接口返回内容
     * @param  string $url [请求的URL地址]
     * @param  string $params [请求的参数]
     * @param  int $ipost [是否采用POST形式]
     * @return  string
     appkey 7949aca2a9b1138d
     */
    public function juhecurl($url,$params=false,$ispost=0){
        $httpInfo = array();
        $ch = curl_init();
        curl_setopt( $ch, CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1 );
        curl_setopt( $ch, CURLOPT_USERAGENT , 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22' );
        curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT , 30 );
        curl_setopt( $ch, CURLOPT_TIMEOUT , 30);
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER , true );
        if( $ispost )
        {
            curl_setopt( $ch , CURLOPT_POST , true );
            curl_setopt( $ch , CURLOPT_POSTFIELDS , $params );
            curl_setopt( $ch , CURLOPT_URL , $url );
        }
        else
        {
            if($params){
                curl_setopt( $ch , CURLOPT_URL , $url.'?'.$params );
            }else{
                curl_setopt( $ch , CURLOPT_URL , $url);
            }
        }
        $response = curl_exec( $ch );
        if ($response === FALSE) {
            //echo "cURL Error: " . curl_error($ch);
            return false;
        }
        $httpCode = curl_getinfo( $ch , CURLINFO_HTTP_CODE );
        $httpInfo = array_merge( $httpInfo , curl_getinfo( $ch ) );
        curl_close( $ch );
        return $response;
    }
    /**
     * 生成签名
     * @return 签名，本函数不覆盖sign成员变量，如要设置签名需要调用SetSign方法赋值
     */
    private function ToUrlParams($urlObj)
    {
        $buff = "";
        foreach ($urlObj as $k => $v)
        {
            if($k != "sign"){
                $buff .= $k . "=" . $v . "&";
            }
        }
        
        $buff = trim($buff, "&");
        return $buff;
    }
}
